package scantask.client.presentationLayer;

import gov.nasa.worldwind.WorldWindow;
import gov.nasa.worldwind.awt.WorldWindowGLCanvas;
import gov.nasa.worldwind.event.SelectEvent;
import gov.nasa.worldwind.event.SelectListener;
import gov.nasa.worldwind.examples.ApplicationTemplate;
import gov.nasa.worldwind.geom.Position;
import gov.nasa.worldwind.layers.AnnotationLayer;
import gov.nasa.worldwind.pick.PickedObjectList;
import gov.nasa.worldwind.render.Annotation;
import gov.nasa.worldwind.render.GlobeAnnotation;
import gov.nasa.worldwind.render.Material;
import gov.nasa.worldwind.render.ScreenAnnotation;
import gov.nasa.worldwind.render.airspaces.AbstractAirspace;
import gov.nasa.worldwind.render.airspaces.Airspace;
import gov.nasa.worldwind.render.airspaces.AirspaceAttributes;
import gov.nasa.worldwind.render.airspaces.BasicAirspaceAttributes;
import gov.nasa.worldwind.util.BasicDragger;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JPanel;

import scantask.client.domainLayer.Controller;
import scantask.client.domainLayer.ControllerInterface;

public class Presentation extends ApplicationTemplate{
	
	public static final String ACTION_COMMAND_ANTIALIAS = "gov.nasa.worldwind.avkey.ActionCommandAntialias";
    public static final String ACTION_COMMAND_DEPTH_OFFSET = "gov.nasa.worldwind.avkey.ActionCommandDepthOffset";
    public static final String ACTION_COMMAND_DRAW_EXTENT = "gov.nasa.worldwind.avkey.ActionCommandDrawExtent";
    public static final String ACTION_COMMAND_DRAW_WIREFRAME = "gov.nasa.worldwind.avkey.ActionCommandDrawWireframe";
    public static final String ACTION_COMMAND_LOAD_DEMO_AIRSPACES = "ActionCommandLoadDemoAirspaces";
    public static final String ACTION_COMMAND_LOAD_INTERSECTING_AIRSPACES = "ActionCommandLoadIntersectingAirspaces";
    public static final String ACTION_COMMAND_ZOOM_TO_DEMO_AIRSPACES = "ActionCommandZoomToDemoAirspaces";
    public static final String ACTION_COMMAND_SAVE_AIRSPACES = "ActionCommandSaveAirspaces";
    public static final String ACTION_COMMAND_READ_AIRSPACES = "ActionCommandReadAirspaces";
    public static final String ACTION_COMMAND_VERTICAL_EXAGGERATION = "ActionCommandVerticalExaggeration";
    public static final String DESCRIPTION = "Description";
	
	public static class AppFrame extends ApplicationTemplate.AppFrame{
		
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;
		
		// Controller to communicate with server.
		private ControllerInterface _controller;
		// The world window of NASA.
		final private WorldWindow _wwd;
		// For tool tips and highlight the 3D shapes.
		final private AirspacesController _shapesController;
	
		public AppFrame() {
			
			super(true, true, false);
			
			this._wwd = this.getWwd();
			this._controller = new Controller();
            
            // Adding a layer for the measurements dates.
            AnnotationLayer screenDates = new AnnotationLayer();
            insertBeforeCompass(this._wwd, screenDates);
            
            this._shapesController = new AirspacesController(this.getWwd());
            
            // Adding panel to the frame.
            this.getLayerPanel().removeAll();
            
            this.getLayerPanel().add(
            		this.makeFunctionalityPanel(screenDates),  BorderLayout.SOUTH);
            
            this.getLayerPanel().add(
            		this.makeUpperPanel(),  BorderLayout.CENTER);
			
            //this.setExtendedState(JFrame.MAXIMIZED_BOTH);
		}
		
		/**
		 * Sets the attributes for the 3D shapes.
		 * @param air is a shape.
		 * @param inCol is the inner color.
		 * @param outCol is the outer color.
		 */
		public static void setAttr(AbstractAirspace air, Color inCol, Color outCol){
			air.setTerrainConforming(true, true);
        	air.getAttributes().setDrawOutline(true);
        	air.getAttributes().setOpacity(0.7);
            air.getAttributes().setOutlineOpacity(0.8);
            air.getAttributes().setOutlineWidth(3.0);
            air.getAttributes().setMaterial(new Material(inCol));
            air.getAttributes().setOutlineMaterial(new Material(outCol));
        }
		
		/**
		 * Sets the attributes for the areas.
		 * @param air is a shape.
		 * @param inCol is the inner color.
		 * @param outCol is the outer color.
		 */
		public static void setAreaAttr(AbstractAirspace air, Color inCol, Color outCol){
			air.setTerrainConforming(true, true);
        	air.getAttributes().setDrawOutline(true);
        	air.getAttributes().setOpacity(0.35);
            air.getAttributes().setOutlineOpacity(0.6);
            air.getAttributes().setOutlineWidth(3.0);
            air.getAttributes().setMaterial(new Material(inCol));
            air.getAttributes().setOutlineMaterial(new Material(outCol));
        }
		
		private JPanel makeFunctionalityPanel(AnnotationLayer layer)
        { 
            return new FunctionalityPanel(
            		this._wwd, this._controller, layer);
        }
		
		private JPanel makeUpperPanel()
        { 
            return new UpperPanel(this._wwd);
        }
		
		public AirspacesController getShapesController(){
			return this._shapesController;
		}
	}
	
	public static class AirspacesController implements ActionListener{
		
		private BasicDragger _dragger;
        private WorldWindowGLCanvas _wwd;
        private AnnotationLayer _annotationLayer;
        private Airspace _lastHighlit;
        private Airspace _lastToolTip;
        private Annotation _lastAnnotation;
        private AirspaceAttributes _lastAttrs;
        
        public AirspacesController(WorldWindowGLCanvas wwd)
        {
            this._wwd = wwd;
            this._annotationLayer = new AnnotationLayer();
            insertBeforePlacenames(this._wwd, this._annotationLayer);
            this.initializeSelectionMonitoring();
        }

		@Override
		public void actionPerformed(ActionEvent e) {
			
		}
		
		public void initializeSelectionMonitoring(){
			AirspacesController.this._dragger = new BasicDragger(this._wwd);
            this._wwd.addSelectListener(new SelectListener(){
                public void selected(SelectEvent event){
                    // Have rollover events highlight the rolled-over object.
                    if ((event.getEventAction().equals(SelectEvent.ROLLOVER)
                    		&& (!AirspacesController.this._dragger.isDragging()))){
                        AirspacesController.this.highlight(event.getTopObject());
                        AirspacesController.this._wwd.redraw();
                    }
                    // Have hover events popup an annotation about the hovered-over object.
                    else if ((event.getEventAction().equals(SelectEvent.HOVER) 
                    		&& (!AirspacesController.this._dragger.isDragging()))){
                        AirspacesController.this.showToolTip(
                        		event.getTopObject(), event);
                        AirspacesController.this._wwd.redraw();
                    }
                    // Have drag events drag the selected object.
                    else if (event.getEventAction().equals(SelectEvent.DRAG_END)
                          || event.getEventAction().equals(SelectEvent.DRAG))
                    {
                        // Delegate dragging computations to a dragger.
                    	//AirspacesController.this._dragger.selected(event);

                        // We missed any roll-over events while dragging, so highlight any under the cursor now,
                        // or de-highlight the dragged shape if it's no longer under the cursor.
                        if (event.getEventAction().equals(SelectEvent.DRAG_END)){
                            PickedObjectList pol = 
                            	AirspacesController.this._wwd.getObjectsAtCurrentPosition();
                            if (pol != null){
                                AirspacesController.this.highlight(pol.getTopObject());
                                AirspacesController.this._wwd.repaint();
                            }
                        }
                    }
                }
            });
        }

		protected void highlight(Object o){
            if (this._lastHighlit == o)
                return; // Same thing selected

            // Turn off highlight if on.
            if (this._lastHighlit != null){
                this._lastHighlit.setAttributes(this._lastAttrs);
                this._lastHighlit = null;
                this._lastAttrs = null;
            }

            // Turn on highlight if selected object is a SurfaceImage.
            if (o instanceof Airspace){
                this._lastHighlit = (Airspace) o;
                this._lastAttrs = this._lastHighlit.getAttributes();
                BasicAirspaceAttributes highlitAttrs = new BasicAirspaceAttributes(
                		this._lastAttrs);
                highlitAttrs.setMaterial(Material.WHITE);
                this._lastHighlit.setAttributes(highlitAttrs);
            }
        }
		
		private void showToolTip(Object o, SelectEvent e){
            if (this._lastToolTip == o)
                return; // Same thing selected

            if ((this._lastToolTip != null) 
            		&& ((e.getTopObject() == null) 
            				|| (!e.getTopObject().equals(this._lastToolTip)))){
                this._annotationLayer.removeAnnotation(this._lastAnnotation);
                this._lastToolTip = null;
            }

            if ((this._lastToolTip == null) && (o instanceof Airspace)){
                this._lastToolTip = (Airspace) o;
                this._lastAnnotation = this.createToolTip((Airspace) o, e);
                this._annotationLayer.addAnnotation(this._lastAnnotation);
            }
        }
		
		private Annotation createToolTip(Airspace a, SelectEvent e){
            Object o = ((AbstractAirspace)a).getDescription();
            if (o == null){
                o = a.getClass().getName();
            }

            java.awt.Point point = e.getPickPoint();

            Annotation annotation;

            Position pos = this._wwd.getView().computePositionFromScreenPoint(point.x, point.y);
            if (pos != null){
                double[] altitudes = a.getAltitudes();
                pos = new Position(pos.getLatitude(), pos.getLongitude(), altitudes[1]);
                annotation = new GlobeAnnotation(o.toString(), pos);
            }
            else{
                annotation = new ScreenAnnotation(o.toString(), point);
            }
            
            annotation.setAlwaysOnTop(true);
            annotation.setPickEnabled(false);

            return annotation;
        }
	}
	
	
	public static void main(String[] args){
		ApplicationTemplate.start("BGU 3D Project", AppFrame.class);
	}
}
